import { isNull, isUndefined, PagedList, PageParams, toString } from "mmb";
import { stringify, v4 as uuid } from "uuid"; // 临时生成订单,将来要切换成自定义生成规则
import {
  Order,
  OrderDetailItem,
  TransactionInfo,
  PlaceOrderResult,
  PlaceOrderDetailItem,
  PlaceOrderParams,
  RepayOrderParams,
  CancelOrderParams,
  DeliverOrderParams,
  PrepareOrderParams,
  PickOrderByBParams,
  PickOrderByCParams,
  ReceiveOrderParams,
  OrderItemForC,
  OrderItemForS,
  OrderItemForB,
  OrderItemForStore,
} from "./declareTypes";
import * as orderpb from "../grpc-client/service/order_pb";
import {
  getBgsOrderOpSafely,
  getMetadata,
  getOptionsOfLight,
  wrapperGrpcError,
} from "../grpc-client/grpcAdapter";
import GrpcErrCode from "../grpc-client/grpcErrCode";
import { numberZeroValue, pbTimestampToJs, jsTimestampToPb } from "./helper";
import OrderStatus from "../bg-enums/orderStatus";
import OrderType from "../bg-enums/orderType";
import DeliveryMode from "../bg-enums/deliveryMode";
import ActivityOwner from "../bg-enums/activityOwner";
import SearchTerm from "../bg-enums/searchTerm";

// 这里订单要考虑归属owner的检测包括:1、品牌管理接口检测品牌是否一致,用户管理接口检测用户是否一致

/****************************************************************************************/
/*                                   order entity                                       */
/****************************************************************************************/

const orderPbToObject = (pb: orderpb.OrderEntity): Order => {
  const o: Order = {
    orderId: toString(pb.getId()),
    ordered: pbTimestampToJs(pb.getOrdered())!,
    serialNumber: pb.getSerialNumber(),
    brandId: toString(pb.getBrandId()),
    activityId: toString(pb.getActivityId()),
    userId: toString(pb.getUserId()),
    userOpenId: pb.getUserOpenId(),
    storeId: pb.getStoreId() === 0 ? undefined : toString(pb.getStoreId()),
    distributorId:
      pb.getDistributorId() === 0 ? undefined : toString(pb.getDistributorId()),
    distributorUserId:
      pb.getDistributorUserId() === 0
        ? undefined
        : toString(pb.getDistributorUserId()),
    spokesmanId: toString(pb.getSpokesmanId()),
    spokesmanUserId: toString(pb.getSpokesmanUserId()),
    orderType: pb.getOrderType() as OrderType,
    orderStatus: pb.getOrderStatus() as OrderStatus,
    deliveryMode: pb.getDeliveryMode() as DeliveryMode,
    remark: pb.getRemark(),
    paymentDeadlineAt: pbTimestampToJs(pb.getPaymentDeadlineAt())!,
    cancelled: pbTimestampToJs(pb.getCancelled()),
    cancelReason: pb.getCancelReason(),
    finished: pbTimestampToJs(pb.getFinished()),
    afterSaleDeadlineAt: pbTimestampToJs(pb.getAfterSaleDeadlineAt()),
    shippingAddress: JSON.parse(pb.getShippingAddress()),
    shippingFee: pb.getShippingFee(),
    productAmount: pb.getProductAmount(),
    amount: pb.getAmount(),
    actualAmount: pb.getActualAmount(),
    isApplyForAfterSale: pb.getIsApplyForAfterSale(),
    isInAfterSale: pb.getIsInAfterSale(),
    details: pb.getOrderDetailsList().map(orderDetailItemPbToObject),
    brandName: pb.getBrandName(),
    brandPic: pb.getBrandPic(),
    brandTel: pb.getBrandTel(),
    storeName: pb.getStoreName() == "" ? undefined : pb.getStoreName(),
    storePic: pb.getStorePic() == "" ? undefined : pb.getStorePic(),
    storeTel: pb.getStoreTel() == "" ? undefined : pb.getStoreTel(),
    activityOwner: pb.getActivityOwner() as ActivityOwner,
    activityName: pb.getActivityName(),
    activityTel: pb.getActivityTel(),
    parentActivityOwner:
      pb.getParentActivityOwner() == ""
        ? undefined
        : (pb.getParentActivityOwner() as ActivityOwner),
    parentActivityName:
      pb.getParentActivityName() == "" ? undefined : pb.getParentActivityName(),
    parentActivityTel:
      pb.getParentActivityTel() == "" ? undefined : pb.getParentActivityTel(),
    buyerNickName: pb.getBuyerNickName(),
    buyerPic: pb.getBuyerPic(),
    buyerTel: pb.getBuyerTel(),
    payType: "wxpay",
  };
  if (o.deliveryMode === DeliveryMode.SELF_PICKUP) {
    const selfPickInfo = pb.getSelfPickInfo()!;
    o.selfPickInfo = {
      address: selfPickInfo.getAddress(),
      linkman: selfPickInfo.getLinkman(),
      tel: selfPickInfo.getTel(),
      code: selfPickInfo.getCode(),
    };
  } else if (o.deliveryMode === DeliveryMode.EXPRESS) {
    const deliverInfo = pb.getDeliverInfo()!;
    o.deliverInfo = {
      platform: deliverInfo.getPlatform(),
      platformOrderNum: deliverInfo.getPlatformOrderNum(),
    };
  }
  return o;
};

const orderDetailItemPbToObject = (
  pb: orderpb.OrderDetailItemEntity
): OrderDetailItem => {
  return {
    orderDetailId: toString(pb.getId()),
    productId: toString(pb.getProductId()),
    productName: pb.getProductName(),
    productSpecId: toString(pb.getProductSpecId()),
    productSpecKey: pb.getProductSpecKey(),
    productSpecName: pb.getProductSpecName(),
    productWithSpecName: pb.getProductWithSpecName(),
    storageKey: pb.getStorageKey(),
    productPics: pb.getProductPicsList(),
    quantity: pb.getQuantity(),
    price: pb.getPrice(),
  };
};

const transactionInfoPbToObject = (
  pb: orderpb.TransactionInfo
): TransactionInfo => {
  return {
    timeStamp: pb.getTimestamp(),
    nonce: pb.getNonce(),
    package: pb.getPackage(),
    signType: pb.getSignType(),
    paySign: pb.getPaySign(),
  };
};

const placeOrderDetailItemObjectToPb = (o: PlaceOrderDetailItem) => {
  const pb = new orderpb.PlaceOrderRequest.PlaceOrderDetailItem();
  pb.setStorageKey(o.storageKey);
  pb.setProductId(Number(o.productId));
  if (!isUndefined(o.productSpecId)) {
    pb.setProductSpecId(Number(o.productSpecId));
  }
  pb.setQuantity(o.quantity);
  pb.setPrice(o.price);
  return pb;
};

/****************************************************************************************/
/*                                   order cmd                                          */
/****************************************************************************************/

export const placeOrder = async ({
  brandId,
  activityId,
  userId,
  userOpenId,
  shareUserId,
  deliveryMode,
  remark,
  shippingAddress,
  shippingFee,
  productAmount,
  amount,
  warehouseId,
  details,
  awardId,
}: PlaceOrderParams): Promise<PlaceOrderResult> => {
  const cl = getBgsOrderOpSafely();
  const req = new orderpb.PlaceOrderRequest();
  req.setBrandId(Number(brandId));
  req.setActivityId(Number(activityId));
  req.setUserId(Number(userId));
  req.setUserOpenId(userOpenId);
  if (!isUndefined(shareUserId)) {
    req.setShareUserId(Number(shareUserId));
  }
  req.setDeliveryMode(deliveryMode);
  if (!isUndefined(remark)) {
    req.setRemark(remark);
  }
  req.setShippingAddress(JSON.stringify(shippingAddress));
  req.setShippingFee(shippingFee);
  req.setProductAmount(productAmount);
  req.setAmount(amount);
  req.setWarehouseid(Number(warehouseId));
  req.setOrderDetailsList(details.map(placeOrderDetailItemObjectToPb));
  if (!isUndefined(awardId)) {
    req.setAwardId(Number(awardId));
  }

  return new Promise((resolve, reject) => {
    cl.placeOrder(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      const order = orderPbToObject(res.getOrder()!);
      const transactionInfo = transactionInfoPbToObject(
        res.getTransactionInfo()!
      );
      resolve({
        order,
        transactionInfo,
      });
    });
  });
};

// 用户重新支付订单
export const repayOrder = async ({
  orderSerialNumber,
  userId,
}: RepayOrderParams): Promise<TransactionInfo> => {
  const cl = getBgsOrderOpSafely();
  const req = new orderpb.RepayOrderRequest();
  req.setOrderSerialNumber(orderSerialNumber);
  req.setUserId(Number(userId));

  return new Promise((resolve, reject) => {
    cl.repayOrder(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(transactionInfoPbToObject(res.getTransactionInfo()!));
    });
  });
};

// 用户撤销订单(具体按未支付后已支付处理不同终态)
export const cancelOrder = async ({
  orderSerialNumber,
  userId,
  cancelReason,
}: CancelOrderParams): Promise<boolean> => {
  const cl = getBgsOrderOpSafely();
  const req = new orderpb.CancelOrderRequest();
  req.setOrderSerialNumber(orderSerialNumber);
  req.setUserId(Number(userId));
  if (!isUndefined(cancelReason)) {
    req.setCancelReason(cancelReason);
  }
  // 未支付单15分钟关闭检查
  return new Promise((resolve, reject) => {
    cl.cancelOrder(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(true);
    });
  });
};

// 商家确认订单备货
export const prepareOrder = async ({
  orderSerialNumber,
  brandId,
}: PrepareOrderParams): Promise<boolean> => {
  const cl = getBgsOrderOpSafely();
  const req = new orderpb.PrepareOrderRequest();
  req.setOrderSerialNumber(orderSerialNumber);
  req.setBrandId(Number(brandId));

  return new Promise((resolve, reject) => {
    cl.prepareOrder(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(true);
    });
  });
};

// 商家确认订单提货
export const pickOrderByB = async ({
  orderSerialNumber,
  pickupCode,
  brandId,
}: PickOrderByBParams): Promise<boolean> => {
  const cl = getBgsOrderOpSafely();
  const req = new orderpb.PickOrderRequest();
  req.setOrderSerialNumber(orderSerialNumber);
  req.setPickupCode(pickupCode);
  req.setBrandId(Number(brandId));

  return new Promise((resolve, reject) => {
    cl.pickOrder(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(true);
    });
  });
};

// 商家确认发货
export const deliverOrder = async ({
  orderSerialNumber,
  brandId,
  platform,
  platformOrderNum,
}: DeliverOrderParams): Promise<boolean> => {
  const cl = getBgsOrderOpSafely();
  const req = new orderpb.DeliverOrderRequest();
  req.setOrderSerialNumber(orderSerialNumber);
  req.setBrandId(Number(brandId));
  req.setPlatform(platform);
  req.setPlatformOrderNum(platformOrderNum);

  // 未支付单15分钟关闭检查
  return new Promise((resolve, reject) => {
    cl.deliverOrder(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(true);
    });
  });
};

// 用户确认提货
export const pickOrderByC = async ({
  orderSerialNumber,
  userId,
}: PickOrderByCParams): Promise<boolean> => {
  const cl = getBgsOrderOpSafely();
  const req = new orderpb.PickOrderRequest();
  req.setOrderSerialNumber(orderSerialNumber);
  req.setUserId(Number(userId));

  return new Promise((resolve, reject) => {
    cl.pickOrder(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(true);
    });
  });
};

// 用户确认收货
export const receiveOrder = async ({
  orderSerialNumber,
  userId,
}: ReceiveOrderParams): Promise<boolean> => {
  const cl = getBgsOrderOpSafely();
  const req = new orderpb.ReceiveOrderRequest();
  req.setOrderSerialNumber(orderSerialNumber);
  req.setUserId(Number(userId));

  return new Promise((resolve, reject) => {
    cl.receiveOrder(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(true);
    });
  });
};

/****************************************************************************************/
/*                                   order query                                        */
/****************************************************************************************/

export const getOrderBySerialNumber = async (
  serialNumber: string
): Promise<Order | undefined> => {
  const cl = getBgsOrderOpSafely();
  const req = new orderpb.GetOrderRequest();
  req.setSerialNumber(serialNumber);
  return new Promise((resolve, reject) => {
    cl.getOrder(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        if (opRet.getCode() === GrpcErrCode.NOT_FOUND) {
          resolve(undefined);
          return;
        } else {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
      }
      resolve(orderPbToObject(res.getOrder()!));
    });
  });
};

export const getOrder = async (orderId: string): Promise<Order | undefined> => {
  const cl = getBgsOrderOpSafely();
  const req = new orderpb.GetOrderRequest();
  req.setOrderId(Number(orderId));
  return new Promise((resolve, reject) => {
    cl.getOrder(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        if (opRet.getCode() === GrpcErrCode.NOT_FOUND) {
          resolve(undefined);
          return;
        } else {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
      }
      resolve(orderPbToObject(res.getOrder()!));
    });
  });
};

/****************************************************************************************/
/*                                   order joins entity                                 */
/****************************************************************************************/

const orderItemForCPbToObject = (
  pb: orderpb.OrderItemForCEntity
): OrderItemForC => {
  return {
    orderId: toString(pb.getId()),
    ordered: pbTimestampToJs(pb.getOrdered())!,
    serialNumber: pb.getSerialNumber(),
    brandId: toString(pb.getBrandId()),
    storeId: pb.getStoreId() === 0 ? undefined : toString(pb.getStoreId()),
    distributorId:
      pb.getDistributorId() === 0 ? undefined : toString(pb.getDistributorId()),
    distributorUserId:
      pb.getDistributorUserId() === 0
        ? undefined
        : toString(pb.getDistributorUserId()),
    activityId: toString(pb.getActivityId()),
    orderType: pb.getOrderType() as OrderType,
    orderStatus: pb.getOrderStatus() as OrderStatus,
    deliveryMode: pb.getDeliveryMode() as DeliveryMode,
    amount: pb.getAmount(),
    paymentDeadlineAt: pbTimestampToJs(pb.getPaymentDeadlineAt())!,
    details: pb.getOrderDetailsList().map(orderDetailItemPbToObject),
    ownerName: pb.getOwnerName(),
    ownerPic: pb.getOwnerPic(),
    ownerTel: pb.getOwnerTel(),
    activityName: pb.getActivityName(),
    activityTel: pb.getActivityTel(),
  };
};

const orderItemForSPbToObject = (
  pb: orderpb.OrderItemForSEntity
): OrderItemForS => {
  return {
    orderId: toString(pb.getId()),
    ordered: pbTimestampToJs(pb.getOrdered())!,
    serialNumber: pb.getSerialNumber(),
    brandId: toString(pb.getBrandId()),
    storeId: pb.getStoreId() === 0 ? undefined : toString(pb.getStoreId()),
    distributorId:
      pb.getDistributorId() === 0 ? undefined : toString(pb.getDistributorId()),
    distributorUserId:
      pb.getDistributorUserId() === 0
        ? undefined
        : toString(pb.getDistributorUserId()),
    activityId: toString(pb.getActivityId()),
    spokesmanId: toString(pb.getSpokesmanId()),
    spokesmanUserId: toString(pb.getSpokesmanUserId()),
    orderType: pb.getOrderType() as OrderType,
    orderStatus: pb.getOrderStatus() as OrderStatus,
    deliveryMode: pb.getDeliveryMode() as DeliveryMode,
    amount: pb.getAmount(),
    details: pb.getOrderDetailsList().map(orderDetailItemPbToObject),
    ownerName: pb.getOwnerName(),
    ownerPic: pb.getOwnerPic(),
    ownerTel: pb.getOwnerTel(),
    activityName: pb.getActivityName(),
    activityTel: pb.getActivityTel(),
    buyerNickName: pb.getBuyerNickName(),
    buyerPic: pb.getBuyerPic(),
  };
};

const orderItemForBPbToObject = (
  pb: orderpb.OrderItemForBEntity
): OrderItemForB => {
  return {
    orderId: toString(pb.getId()),
    ordered: pbTimestampToJs(pb.getOrdered())!,
    serialNumber: pb.getSerialNumber(),
    brandId: toString(pb.getBrandId()),
    activityId: toString(pb.getActivityId()),
    orderType: pb.getOrderType() as OrderType,
    orderStatus: pb.getOrderStatus() as OrderStatus,
    deliveryMode: pb.getDeliveryMode() as DeliveryMode,
    amount: pb.getAmount(),
    isApplyForAfterSale: pb.getIsApplyForAfterSale(),
    isInAfterSale: pb.getIsInAfterSale(),
    details: pb.getOrderDetailsList().map(orderDetailItemPbToObject),
    brandName: pb.getBrandName(),
    brandPic: pb.getBrandPic(),
    brandTel: pb.getBrandTel(),
    activityName: pb.getActivityName(),
    activityTel: pb.getActivityTel(),
    buyerNickName: pb.getBuyerNickName(),
    buyerPic: pb.getBuyerPic(),
  };
};

const orderItemForStorePbToObject = (
  pb: orderpb.OrderItemForStoreEntity
): OrderItemForStore => {
  return {
    orderId: toString(pb.getId()),
    ordered: pbTimestampToJs(pb.getOrdered())!,
    serialNumber: pb.getSerialNumber(),
    brandId: toString(pb.getBrandId()),
    storeId: toString(pb.getStoreId()),
    distributorId: toString(pb.getDistributorId()),
    distributorUserId: toString(pb.getDistributorUserId()),
    activityId: toString(pb.getActivityId()),
    orderType: pb.getOrderType() as OrderType,
    orderStatus: pb.getOrderStatus() as OrderStatus,
    deliveryMode: pb.getDeliveryMode() as DeliveryMode,
    amount: pb.getAmount(),
    isApplyForAfterSale: pb.getIsApplyForAfterSale(),
    isInAfterSale: pb.getIsInAfterSale(),
    details: pb.getOrderDetailsList().map(orderDetailItemPbToObject),
    storeName: pb.getStoreName(),
    storePic: pb.getStorePic(),
    storeTel: pb.getStoreTel(),
    activityName: pb.getActivityName(),
    activityTel: pb.getActivityTel(),
    buyerNickName: pb.getBuyerNickName(),
    buyerPic: pb.getBuyerPic(),
  };
};
/****************************************************************************************/
/*                                   order joins query                                  */
/****************************************************************************************/

export interface listOrderItemsForSParam {
  userId: string;
  isAll: boolean;
  orderStatuses?: OrderStatus[];
}

export const listOrderItemsForC = async (
  { userId, isAll, orderStatuses }: listOrderItemsForSParam,
  pager: PageParams
): Promise<PagedList<OrderItemForC>> => {
  const cl = getBgsOrderOpSafely();
  const req = new orderpb.ListOrderItemsForCRequest();

  req.setLimit(pager.limit);
  req.setOffset(pager.offset);
  req.setTs(jsTimestampToPb(pager.ts));
  req.setUserId(Number(userId));
  req.setIsAll(isAll);
  if (!isUndefined(orderStatuses)) {
    req.setOrderStatusesList(orderStatuses);
  }

  return new Promise((resolve, reject) => {
    cl.listOrderItemsForC(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        const ret: PagedList<OrderItemForC> = {
          total: 0,
          items: [],
        };
        ret.total = res.getTotal();
        ret.items = res.getOrderItemsForCList().map(orderItemForCPbToObject);
        resolve(ret);
      }
    );
  });
};

export interface listOrderItemsForSParam {
  userId: string;
  isAll: boolean;
  orderStatuses?: OrderStatus[];
  searchTerm?: SearchTerm;
  searchValue?: string;
}

export const listOrderItemsForS = async (
  {
    userId,
    isAll,
    orderStatuses,
    searchTerm,
    searchValue,
  }: listOrderItemsForSParam,
  pager: PageParams
): Promise<PagedList<OrderItemForS>> => {
  const cl = getBgsOrderOpSafely();
  const req = new orderpb.ListOrderItemsForSRequest();

  req.setLimit(pager.limit);
  req.setOffset(pager.offset);
  req.setTs(jsTimestampToPb(pager.ts));
  req.setUserId(Number(userId));
  req.setIsAll(isAll);
  if (!isUndefined(orderStatuses)) {
    req.setOrderStatusesList(orderStatuses);
  }
  if (!isUndefined(searchTerm)) {
    req.setSearchTerm(searchTerm);
  }
  if (!isUndefined(searchValue)) {
    req.setSearchValue(searchValue);
  }

  return new Promise((resolve, reject) => {
    cl.listOrderItemsForS(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        const ret: PagedList<OrderItemForS> = {
          total: 0,
          items: [],
        };
        ret.total = res.getTotal();
        ret.items = res.getOrderItemsForSList().map(orderItemForSPbToObject);
        resolve(ret);
      }
    );
  });
};

export interface listOrderItemsForBParam {
  brandId: string;
  isAll: boolean;
  orderStatuses?: OrderStatus[];
  searchTerm?: SearchTerm;
  searchValue?: string;
}

export const listOrderItemsForB = async (
  {
    brandId,
    isAll,
    orderStatuses,
    searchTerm,
    searchValue,
  }: listOrderItemsForBParam,
  pager: PageParams
): Promise<PagedList<OrderItemForB>> => {
  const cl = getBgsOrderOpSafely();
  const req = new orderpb.ListOrderItemsForBRequest();

  req.setLimit(pager.limit);
  req.setOffset(pager.offset);
  req.setTs(jsTimestampToPb(pager.ts));
  req.setBrandId(Number(brandId));
  req.setIsAll(isAll);
  if (!isUndefined(orderStatuses)) {
    req.setOrderStatusesList(orderStatuses);
  }
  if (!isUndefined(searchTerm)) {
    req.setSearchTerm(searchTerm);
  }
  if (!isUndefined(searchValue)) {
    req.setSearchValue(searchValue);
  }

  return new Promise((resolve, reject) => {
    cl.listOrderItemsForB(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        const ret: PagedList<OrderItemForB> = {
          total: 0,
          items: [],
        };
        ret.total = res.getTotal();
        ret.items = res.getOrderItemsForBList().map(orderItemForBPbToObject);
        resolve(ret);
      }
    );
  });
};

export interface listOrderItemsForStoreParam {
  storeId: string;
  isAll: boolean;
  orderStatuses?: OrderStatus[];
  searchTerm?: SearchTerm;
  searchValue?: string;
}

export const listOrderItemsForStore = async (
  {
    storeId,
    isAll,
    orderStatuses,
    searchTerm,
    searchValue,
  }: listOrderItemsForStoreParam,
  pager: PageParams
): Promise<PagedList<OrderItemForStore>> => {
  const cl = getBgsOrderOpSafely();
  const req = new orderpb.ListOrderItemsForStoreRequest();

  req.setLimit(pager.limit);
  req.setOffset(pager.offset);
  req.setTs(jsTimestampToPb(pager.ts));
  req.setStoreId(Number(storeId));
  req.setIsAll(isAll);
  if (!isUndefined(orderStatuses)) {
    req.setOrderStatusesList(orderStatuses);
  }
  if (!isUndefined(searchTerm)) {
    req.setSearchTerm(searchTerm);
  }
  if (!isUndefined(searchValue)) {
    req.setSearchValue(searchValue);
  }

  return new Promise((resolve, reject) => {
    cl.listOrderItemsForStore(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        const ret: PagedList<OrderItemForStore> = {
          total: 0,
          items: [],
        };
        ret.total = res.getTotal();
        ret.items = res
          .getOrderItemsForStoreList()
          .map(orderItemForStorePbToObject);
        resolve(ret);
      }
    );
  });
};
